#include "Unit.h"

Unit::Unit()
{
}

Unit::~Unit()
{
   for (vector< list<Connection*>* >::iterator i = mAudioIn.begin();
        i != mAudioIn.end();
        i ++)
   {
      for (list<Connection*>::iterator ci = (*i)->begin();
           ci != (*i)->end();
           ci ++)
      {
         delete (*ci);
      }
      delete (*i);
   }

   for (vector< list<Connection*>* >::iterator i = mDataOut.begin();
        i != mDataOut.end();
        i ++)
   {
      for (list<Connection*>::iterator ci = (*i)->begin();
           ci != (*i)->end();
           ci ++)
      {
         delete (*ci);
      }
      delete (*i);
   }
}

void Unit::createPorts(unsigned audioPorts, unsigned dataPorts)
{
   for (unsigned i = 0; i < audioPorts; i ++)
      mAudioIn.push_back(new list<Connection*>);
   for (unsigned i = 0; i < dataPorts; i ++)
      mDataOut.push_back(new list<Connection*>);
}

Unit& Unit::ctl(unsigned port, Message msg)
{
   return *this;
}

void Unit::readFromPort(unsigned port, sample_t *buffer, jack_nframes_t len, Options options)
{
   Options opt = options;
   opt.setAddition(true);

   for (list<Connection*>::iterator ci = mAudioIn[port]->begin();
         ci != mAudioIn[port]->end();
         ci ++)
   {
      /* read from connected units if any */
      if ((*ci)->getSrcPort() == port)
         (*ci)->getUnit()->ar((*ci)->getDstPort(), buffer, len, options);

      if (!options.isAddition) break;
   }
}

void Unit::addPort(string name, PortType type, PortIOType iotype)
{ 
   mPorts.push_back(new Port(name, type, iotype));
}

list<Connection*>* Unit::getConnections(unsigned port)
{
   if (port >= getAudioPortCount())
      textException("getConnections: wrong port number");
   return mAudioIn[port];
}

void connect(Unit *srcUnit, Unit *dstUnit, unsigned srcPort, unsigned dstPort)
{
   if (dstPort >= dstUnit->getAudioPortCount())
      textException("connect: wrong port number");

   dstUnit->mAudioIn[dstPort]->push_back(new Connection(srcPort, srcUnit, dstPort));
}
void connect(Unit &srcUnit, Unit &dstUnit, unsigned srcPort, unsigned dstPort)
{
   if (dstPort >= dstUnit.getAudioPortCount())
      textException("connect: wrong port number");

   dstUnit.mAudioIn[dstPort]->push_back(new Connection(srcPort, &srcUnit, dstPort));
}

Dac::Dac()
{
   setName("dac");
   createPorts(1, 0);
}
void Dac::ar(unsigned port, sample_t *buffer, jack_nframes_t len, Options options)
{
   Options opt = options.setAddition(true);

   if (port >= getAudioPortCount())
      textException("ar: wrong port number");

   readFromPort(port, buffer, len, opt);
}
